package com.foreverwin.jzymes.production.nc.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.foreverwin.jzymes.common.domain.CarrierBind;
import com.foreverwin.jzymes.common.domain.NcData;
import com.foreverwin.jzymes.common.enums.DispositionEnum;
import com.foreverwin.jzymes.common.mapper.CarrierBindMapper;
import com.foreverwin.jzymes.common.mapper.NcDataMapper;
import com.foreverwin.jzymes.common.service.*;
import com.foreverwin.jzymes.common.util.CommonMethods;
import com.foreverwin.jzymes.framework.event.AppEvent;
import com.foreverwin.jzymes.framework.event.AppEventPublisher;
import com.foreverwin.jzymes.framework.exception.BusinessException;
import com.foreverwin.jzymes.framework.util.I18nUtil;
import com.foreverwin.jzymes.framework.util.ObjectMapperUtil;
import com.foreverwin.jzymes.production.nc.service.ICarrierNCDisposeAdviceService;
import com.foreverwin.jzymes.production.sfc.mapper.SFCMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class CarrierNCDisposeAdviceServiceImpl implements ICarrierNCDisposeAdviceService {

    @Autowired
    ISiteAdviceService siteAdviceService;
    @Autowired
    IResourceAdviceService resourceAdviceService;
    @Autowired
    INCDataAdviceService incDataAdviceService;
    @Autowired
    INCDataAdviceService ncDataAdviceService;
    @Autowired
    ICarrierBindAdviceService carrierBindAdviceService;
    @Autowired
    ICommonService commonService;
    @Autowired
    ISfcBatchPassLogAdviceService sfcBatchPassLogAdviceService;
    @Autowired
    IActivityLogAdviceService activityLogAdviceService;
    @Autowired
    INCCodeAdviceService ncCodeAdviceService;
    @Autowired
    IResourceTypeAdviceService resourceTypeAdviceService;
    @Autowired
    NcDataMapper ncDataMapper;
    @Autowired
    SFCMapper sfcMapper;
    @Autowired
    CarrierBindMapper carrierBindMapper;
    @Autowired
    AppEventPublisher appEventPublisher;


    /**
     * 不良处置
     *
     * @param jsonMap
     */
    @Transactional( propagation = Propagation.REQUIRED, rollbackFor = Exception.class )
    public void disposeCarrierNC( Map<String,Object> jsonMap, boolean autoPass ){
        /**检查不良处置字段*/
        checkFieldsForDisposeNC( jsonMap );

        /**检查不良明细*/
        List<Map<String,Object>> ncList = (List<Map<String, Object>>) jsonMap.get( "ncList" );
        Assert.isTrue( ncList != null && ncList.size() > 0, I18nUtil.getI18nText( "production.nc.ncListNotNull" ) );

        /**添加公用字段*/
        jsonMap.remove( "ncList" );
        for( Map<String,Object> map : ncList ){
            map.putAll( jsonMap );
        }
        List<NcData> ncDataList = ObjectMapperUtil.convertList( ncList, NcData.class );
        disposeCarrierNC( (String) jsonMap.get( "site" ), (String) jsonMap.get("carrier"), (String) jsonMap.get("resrce"), ncDataList, new Date(), autoPass );

    }

    public void disposeCarrierNC( String site, String carrier, String resource, List<NcData> ncDataList, Date updatedDateTime, boolean autoPass ){
        boolean rework = false;
        for( NcData ncData : ncDataList ){

            /**检查物料本体绑定状态*/
            CarrierBind carrierBind = carrierBindAdviceService.findCarrierBindOnBindByItem( ncData.getSite(), ncData.getCarrier(), ncData.getItemBo() );

            /**本体在工序已过站则不允许再处置不良数据*/
            boolean passed = commonService.checkCarrierPassOnOperation( carrierBind, ncData.getOperation() );
            Assert.isTrue( passed == false, I18nUtil.getI18nText( "production.nc.carrierPassOnOperation", new Object[]{ ncData.getCarrier(), ncData.getOperation() } ) );

            /**检查本体物料不良项目是否存在*/
            NcData ncData1 = ncDataAdviceService.findItemOpenNcDataFromDate( ncData.getSite(), ncData.getCarrier(), ncData.getItemBo(), ncData.getOperation() );
            Assert.notNull( ncData1, I18nUtil.getI18nText("production.nc.carrierItemNCNotExist", new Object[]{ ncData.getCarrier(), ncData.getItemBo(), ncData.getOperation() } ) );

            ncData1.setDisposition( ncData.getDisposition() );
            ncData1.setUpdatedDateTime( updatedDateTime );
            ncData1.setUpdateUserBo( CommonMethods.getUserBo() );

            /**检查nc是否处置*/
            checkNcDataNotDispose( ncData1 );

            /**处置方式报废*/
            if( DispositionEnum.SCRAP.getValue().equals( ncData1.getDisposition() ) ){
                scrapNCData( ncData1 );

                JSONObject eventData = new JSONObject();
                eventData.put( "SITE", ncData1.getSite() );
                eventData.put( "ITEM_BO", ncData1.getItemBo() );
                eventData.put( "RESRCE", resource );
                eventData.put( "QTY", ncData1.getNcQty() );
                AppEvent<JSONObject> appEvent = new AppEvent<>( this );
                appEvent.setName( "ITEM_NC_SCRAP_EVENT" );
                appEvent.setData( eventData );
                appEventPublisher.publishEvent( appEvent );
                continue;
            }

            /**处置方式返工*/
            if( DispositionEnum.REWORK.getValue().equals( ncData1.getDisposition() ) ){
                /*rework = true;
                ncData1.setIsRework( "true" );*/
                throw BusinessException.build( "production.nc.disposeNotAllowRework", new String[]{ ncData.getCarrier(), ncData.getItemBo(), ncData.getNcCode() } );
            }

            ncDataMapper.updateNcData( ncData1 );
        }

        if( !rework && autoPass ){
            commonService.sfcPassByCarrier( site, carrier, resource, updatedDateTime );

            JSONObject eventData = new JSONObject();
            eventData.put( "SITE", site );
            eventData.put( "CARRIER", carrier );
            eventData.put( "RESRCE", resource );
            AppEvent<JSONObject> appEvent = new AppEvent<>( this );
            appEvent.setName( "CARRIER_NC_CHECK_OUT_EVENT" );
            appEvent.setData( eventData );
            appEventPublisher.publishEvent( appEvent );
        }
    }

    /**
     * 检查未处置的不良项目
     *
     * @param ncData
     */
    public void checkNcDataNotDispose( NcData ncData ){
        if( StringUtils.isBlank( ncData.getDisposition() ) ){
            String futureOperation = ncCodeAdviceService.findNCValidOper( ncData.getSite(), ncData.getNcCode() );
            if( StringUtils.isBlank( futureOperation ) ){
                throw BusinessException.build("production.nc.carrierNcNotDispose",new String[]{ ncData.getCarrier(), ncData.getItemBo(),ncData.getNcCode() } );
            }else{
                ncData.setOperation( futureOperation );
            }
        }
    }

    /**
     * nc处置报废
     *
     * @param ncData
     */
    public void scrapNCData( NcData ncData ){
        if( resourceAdviceService.isCNC1( ncData.getSite(), ncData.getResrce() ) ){
            /**扣减工令批次过站数量*/
            commonService.reduceOpenSfcBatchPassLogQty( ncData.getSite(), ncData.getItemBo(), ncData.getResrce(), ncData.getNcQty() );
        }
        /**报废MES工令数量*/
        commonService.scrapSfcQty( ncData.getSite(), ncData.getSfc(), ncData.getResrce(), ncData.getNcQty(), ncData.getCreatedDateTime() );
        /**料件和本体解绑*/
        carrierBindAdviceService.carrierUnBind( ncData.getSite(),ncData.getCarrier(), ncData.getItemBo(), ncData.getCreatedDateTime() );
        ncDataMapper.updateNcData( ncData );
    }



    /**
     * 检查不良处置字段
     *
     * @param jsonMap
     */
    public void checkFieldsForDisposeNC( Map<String,Object> jsonMap ){
        /**检查站点*/
        siteAdviceService.existSite((String) jsonMap.get( "site" ));
        /**检查设备*/
        Map<String,Object> resourceMap = resourceAdviceService.existResource( (String) jsonMap.get( "site" ), (String) jsonMap.get( "resrce" ));
        /**检查工序*/
        String operation = resourceAdviceService.findOperationByResource( resourceMap );
        jsonMap.put( "operation", operation );
        /**检查本体*/
        Assert.hasText( ( String )jsonMap.get( "carrier" ), I18nUtil.getI18nText( "common.carrierNotBlank" ));
    }

    /**
     * 查询本体打开不良明细
     *
     * @param jsonMap
     * @return
     */
    public List<NcData> findCarrierOpenNcData( Map<String,Object> jsonMap ){
        String site = (String) jsonMap.get( "site" );
        String operation = (String) jsonMap.get( "operation" );
        String carrier = (String) jsonMap.get( "carrier" );

        /**检查站点*/
        siteAdviceService.existSite( site );
        /**检查本体*/
        Assert.hasText( carrier, I18nUtil.getI18nText( "common.carrierNotBlank" ));
        /**检查工序*/
        Assert.hasText( operation, I18nUtil.getI18nText( "common.operationNotBlank" ) );

        List<NcData> ncDataList = ncDataAdviceService.findOpenNcDataFromDate( site, carrier, operation );
        return ncDataList;
    }
}
